import { Connection } from 'diagram-js/lib/model'
import { ModdleElement } from 'bpmn-moddle'
import { getBusinessObject, is, isAny } from 'bpmn-js/lib/util/ModelUtil'
import { getEventDefinition } from './bpmnPropertyUtils/eventDefinition'
import { createModdleElement } from './bpmnPropertyUtils/extensionElements'
import { useSettingStore } from '@/store/bpmnProcess/settingStore'
import { useModelerStore } from '@/store/bpmnProcess/modelerStore'

// /////////////////////////////// 配置项可见性
const CONDITIONAL_SOURCES = ['bpmn:Activity', 'bpmn:ExclusiveGateway', 'bpmn:InclusiveGateway', 'bpmn:ComplexGateway']

export const circulationTypeOptions: Record<string, string>[] = [
  { label: '普通流转路径', value: 'normal' },
  { label: '默认流转路径', value: 'default' },
  { label: '条件流转路径', value: 'condition' }
]

export const conditionTypeOptions: Record<string, string>[] = [
  { label: '脚本', value: 'script' },
  { label: '表达式', value: 'expression' }
]

// 父节点符合条件的连线
export function isConditionalSource(element) {
  return isAny(element, CONDITIONAL_SOURCES)
}
// 是否是 定义条件的事件 （ 控制变量 Variables 配置 ）
export function isConditionEventDefinition(element): boolean {
  return is(element, 'bpmn:Event') && !!getEventDefinition(element, 'bpmn:ConditionalEventDefinition')
}
export function isExtendStartEvent(element): boolean {
  return is(element, 'bpmn:StartEvent')
}
// 元素 是否符合 可以设置条件 的情况
export function isCanBeConditional(element): boolean {
  return (is(element, 'bpmn:SequenceFlow') && isConditionalSource((element as Connection)?.source)) || isConditionEventDefinition(element)
}

// /////////////////////////
// 1. 条件变量部分
export function getVariableNameValue(element): string | undefined {
  if (getConditionalEventDefinition(element)) {
    return (getConditionalEventDefinition(element) as ModdleElement).get('variableName')
  }
}
export function setVariableNameValue(element, value: string | undefined) {
  const modeling = useModelerStore().getModeling
  const eventDefinition = getConditionalEventDefinition(element)
  if (eventDefinition) {
    modeling.updateModdleProperties(element, eventDefinition, { variableName: value || '' })
  }
}

// 2. 条件事件部分
export function getVariableEventsValue(element): string | undefined {
  if (getConditionalEventDefinition(element)) {
    return (getConditionalEventDefinition(element) as ModdleElement).get('variableEvents')
  }
}
export function setVariableEventsValue(element, value: string | undefined) {
  const modeling = useModelerStore().getModeling
  const eventDefinition = getConditionalEventDefinition(element)
  if (eventDefinition) {
    modeling.updateModdleProperties(element, eventDefinition, { variableName: value || '' })
  }
}

// 3. 元素条件类型
export function getConditionTypeValue(element): string {
  const conditionExpression = getConditionExpression(element)
  if (conditionExpression) {
    return conditionExpression.get('language') === undefined ? 'expression' : 'script'
  }
  if (element.source?.businessObject?.default === element.businessObject) return 'default'
  return 'normal'
}
export function setConditionTypeValue(element, value: string) {
  if (!value || value === 'normal' || value === 'default') {
    updateCondition(element)
    return setDefaultCondition(element as Connection, value === 'default')
  }
  const attributes = {
    // body: '',
    language: value === 'script' ? '' : undefined
  }
  const parent = is(element, 'bpmn:SequenceFlow') ? getBusinessObject(element) : (getConditionalEventDefinition(element) as ModdleElement)
  const formalExpressionElement = createModdleElement('bpmn:FormalExpression', attributes, parent)
  updateCondition(element, formalExpressionElement)
}

// 4. 元素条件表达式
export function getConditionExpressionValue(element): string | undefined {
  const conditionExpression = getConditionExpression(element)
  if (conditionExpression) {
    return conditionExpression.get('body')
  }
}
export function setConditionExpressionValue(element, body: string | undefined) {
  const parent = is(element, 'bpmn:SequenceFlow') ? getBusinessObject(element) : (getConditionalEventDefinition(element) as ModdleElement)
  const formalExpressionElement = createModdleElement('bpmn:FormalExpression', { body }, parent)
  updateCondition(element, formalExpressionElement)
}

// 5. 元素脚本来源类型
export function getConditionScriptTypeValue(element): string | undefined {
  const prefix = useSettingStore().editor.processEngine
  const conditionExpression = getConditionExpression(element)
  console.log(conditionExpression)
  if (conditionExpression.get('body') !== undefined) return 'inline'
  if (conditionExpression.get(`${prefix}:resource`) !== undefined) return 'external'
  return ''
}
export function setConditionScriptTypeValue(element, value: string | undefined) {
  const prefix = useSettingStore().editor.processEngine
  const modeling = useModelerStore().getModeling
  let props
  if (!value) {
    props = { body: undefined, [`${prefix}:resource`]: undefined }
  }
  if (value === 'inline') {
    props = { body: '', [`${prefix}:resource`]: undefined }
  }
  if (value === 'external') {
    props = { body: undefined, [`${prefix}:resource`]: '' }
  }
  modeling.updateModdleProperties(element, getConditionExpression(element), props)
}

// 6. 元素脚本 语言类型
export function getConditionScriptLanguageValue(element): string | undefined {
  return getConditionExpression(element)?.get('language')
}
export function setConditionScriptLanguageValue(element, value: string | undefined) {
  const modeling = useModelerStore().getModeling
  modeling.updateModdleProperties(element, getConditionExpression(element), { language: value })
}

// 7. 元素脚本 body
export function getConditionScriptBodyValue(element): string | undefined {
  return getConditionExpression(element)?.get('body')
}
export function setConditionScriptBodyValue(element, value: string | undefined) {
  const modeling = useModelerStore().getModeling
  modeling.updateModdleProperties(element, getConditionExpression(element), { body: value })
}

// 8. 元素脚本 source
export function getConditionScriptResourceValue(element): string | undefined {
  const prefix = useSettingStore().editor.processEngine
  return getConditionExpression(element)?.get(`${prefix}:resource`)
}
export function setConditionScriptResourceValue(element, value: string | undefined) {
  const modeling = useModelerStore().getModeling
  const prefix = useSettingStore().editor.processEngine
  modeling.updateModdleProperties(element, getConditionExpression(element), {
    [`${prefix}:resource`]: value
  })
}

// /////// helpers
function getConditionalEventDefinition(element): ModdleElement | false | undefined {
  if (!is(element, 'bpmn:Event')) return false
  return getEventDefinition(element, 'bpmn:ConditionalEventDefinition')
}

// 获取给定元素的条件表达式的值
function getConditionExpression(element): ModdleElement | undefined {
  const businessObject = getBusinessObject(element)
  if (is(businessObject, 'bpmn:SequenceFlow')) {
    return businessObject.get('conditionExpression')
  }
  if (getConditionalEventDefinition(businessObject)) {
    return (getConditionalEventDefinition(businessObject) as ModdleElement).get('condition')
  }
}

//
function updateCondition(element, condition?: string | ModdleElement) {
  const modeling = useModelerStore().getModeling
  if (is(element, 'bpmn:SequenceFlow')) {
    modeling.updateProperties(element, { conditionExpression: condition })
  } else {
    modeling.updateModdleProperties(element, getConditionalEventDefinition(element), { condition })
  }
}

//
function setDefaultCondition(element: Connection, isDefault: boolean) {
  const modeling = useModelerStore().getModeling
  modeling.updateProperties(element.source, { default: isDefault ? element : undefined })
}
